if heat.heaters[0].state == "fault" || heat.heaters[1].state == "fault" || heat.heaters[2].state == "fault" || heat.heaters[3].state == "fault"
  M291 S1 R"Error" P"Heater fault detected"
  abort "Error: Heater fault detected"

M291 S5 J1 F250 L0 H450 R"Set Left Tool Temperature" P"Please set the temperature for the filament previously loaded in the Left Tool.<br>If new machine, set to 250°C"
var ll = input
  
M291 S5 J1 F{var.ll} L0 H450 R"Set Right Tool Temperature" P"Please set the temperature for the filament previously loaded in the Right Tool.<br>If new machine, set to 250°C"
var rr = input

var delta = -50

M568 P0 R{var.ll + var.delta} S{var.ll + var.delta}
M568 P1 R{var.rr + var.delta} S{var.rr + var.delta}
M568 P2 R{var.ll + var.delta,var.rr + var.delta} S{var.ll + var.delta,var.rr + var.delta}
M568 P3 R{var.ll + var.delta,var.rr + var.delta} S{var.ll + var.delta,var.rr + var.delta}

M568 P0 A2
M568 P1 A2


M291 S2 R"Please Remove the Build Plate" P"To avoid damaging your machine, remove the build plate from the build platform.<br>Click ""OK"" when you are ready to proceed."

if !move.axes[0].homed || !move.axes[1].homed || !move.axes[2].homed || !move.axes[3].homed
  M291 S0 T15 R"Homing Axes" P"Axes are not homed. Homing now. Please wait..."
  M98 P"0:/sys/homeall.g" S1

if state.currentTool != 0
  T0

G90
G1 X-999 U999 Y-75 F18000

M116 P0 S10
M116 P1 S10

T3
M83                 ; relative extruder moves
G1 E-50 F{60}*{10}   ; retract filament

M98 P"0:/sys/nozzlewipe.g" C1
M400
while iterations < 2
  M98 P"0:/sys/nozzlewipe.g" L1 C1
  M400

G1 F18000 X-50 Y-150 Z125  ; Move tools to the cleaning position

M568 P3 A0

M291 S4 K{"Nozzles are Clean","Cancel"} R"Please Clean Both Nozzles" P"Use a metal brush to clean both nozzles thoroughly to prevent machine damage."

if input == 1
  ; User cancelled
  M568 P0 S0 R0
  M568 P1 S0 R0
  M568 P2 S0 R0
  M568 P3 S0 R0
  abort "Calibration cancelled by user"

var ref = "<a href=""https://wiki.visionminer.com/docs/v4/calibration/auto-calibration#heat-break-check"">Heat Break Check Guide</a>"
M291 S4 K{"Heat Breaks are All the Way Up","Cancel"} R"Verify Heat Break Position" P{"Ensure both heat breaks are pushed all the way up into the heat sink. They must NOT stick out more than 1mm.<br><br>" ^ var.ref}

if input == 1
  ; User cancelled
  M568 P0 S0 R0
  M568 P1 S0 R0
  M568 P2 S0 R0
  M568 P3 S0 R0
  abort "Calibration cancelled by user"

M568 P3 A2

M98 P"0:/sys/homeall.g" S1 L1

G29 S2     ; disable Mesh Bed Leveling
M290 R0 S0
M208 Z-10 S1
M558 K0 P8 C"1.io4.in" H5 F100 T18000              ; define Z probe parameters
M98 P"0:/sys/user/actions/ProbeOffset.g"           ; load global variables
T0
G1 U999 F18000
M42 P4 S1                                              ; Turn on relay






M98 P"0:/macros/System/Calibration/QC/AutoCal/Tool Height Auto Calibration" A1
M400

M98 P"0:/macros/System/Calibration/QC/AutoCal/Z - Offset Calibration" A1
M400

if global.xCompMode == "manual"
  echo "Skipping Mesh Bed calibration because compensation mode is manual"
else
  M98 P"0:/macros/System/Calibration/QC/AutoCal/Mesh Bed Calibration" A1
  M400

; Check if either XY squaring or steps/mm calibration is enabled
var runCalibration = false

; Load both mode states
M98 P"0:/sys/user/variables/XySquareMode.g"
M98 P"0:/sys/user/variables/StepsCalibration.g"
M98 P"0:/sys/user/actions/StepsCalibration.g"

; Check XY squaring mode (enabled if mode is "auto")
if global.xySquareMode == "auto"
  set var.runCalibration = true

; Check steps/mm calibration mode (enabled if true)
if global.stepsCalibration == true
  set var.runCalibration = true

; Run calibration only if at least one mode is enabled
if var.runCalibration
  M98 P"0:/macros/System/Calibration/QC/AutoCal/XY Auto Squaring" A1
  M400
  M98 P"0:/sys/xy_squaring.g"
  M400
else
  echo "Skipping XY Auto Squaring - both XY squaring and steps/mm calibration are disabled"

M98 P"0:/macros/System/Calibration/QC/AutoCal/XY - Offset Calibration" A1
M400



M568 P0 S0 R0
M568 P1 S0 R0
M568 P2 S0 R0
M568 P3 S0 R0

M208 Z-1 S1
M558 K0 P8 C"1.io4.in" H5 F300 T18000
M98 P"0:/sys/user/actions/ProbeOffset.g"

M98 P"0:/sys/detachedcheck.g"

if move.axes[0].homed && move.axes[1].homed && move.axes[2].homed && move.axes[3].homed
  G90
  G1 X-999 U999 Y150 Z100 F18000

; Build calibration results message
var msg = "Auto Calibration Successful"
set var.msg = var.msg ^ "<br>Tool 1 Z Offset = " ^ global.tool1ZOffset ^ " mm"
set var.msg = var.msg ^ "<br>Z-Offset = " ^ global.zOffset ^ " mm"
set var.msg = var.msg ^ "<br>Tool 1 Y-Offset = " ^ global.yOffset ^ " mm"
set var.msg = var.msg ^ "<br>Tool 1 U-Offset = " ^ global.uOffset ^ " mm"
set var.msg = var.msg ^ "<br>XY Skew = " ^ global.xySquareAuto ^ " mm"
M291 S2 R"Calibration Complete" P{var.msg}